from skillchallenge.models import *
import EventEngine
import CodeEngine
import LocationEngine
import NPCEngine
from django.db.models import Q

class ItemEngine:
    
    DROP = 'drop'
    PICK = 'pick'
    GIVE = 'give'
    RECEIVE = 'receive'
    SEE = 'see'
    
    event_engine = EventEngine.EventEngine()
    code_engine = CodeEngine.CodeEngine()
    location_engine = LocationEngine.LocationEngine()
    npc_engine = NPCEngine.NPCEngine()
    
    def create_item(self, name):
        return Item.objects.create(name = name)

    def create_see_event(self, item, location):
        return self.event_engine.add_event(preconditions = [self.location_engine.is_in_precon(location),
                                                 self.is_in_inventory(item, negate=True)],
                             actions = [self.code_engine.create_message_action('you see ' + item.name + '.')],
                             recurring = True, online=True, info= self.__info__(self.SEE, item))
        
    def create_pick_event(self, item, location, always_droppable = False):        
        return self.event_engine.add_event(player_will = True,
                                preconditions = [self.location_engine.is_in_precon(location)],
                                actions = [self.code_engine.create_message_action('you get ' + item.name + '.')],
                                info = self.__info__(self.PICK, item, location), online=True)
        
    def create_drop_event(self, item, location, always_pickable = False):        
        return self.event_engine.add_event(player_will = True,
                                preconditions = [self.is_in_inventory(item), self.location_engine.is_in_precon(location)],
                                actions = [self.code_engine.create_message_action('you drop ' + item.name + '.')],
                                info = self.__info__(self.DROP, item, location), online=True)
    
    def create_give_event(self, item, npc):        
        return self.event_engine.add_event(player_will = True,
                                preconditions = [self.is_in_inventory(item), self.npc_engine.is_in_same_precon(npc)],
                                actions = [self.code_engine.create_message_action('you give ' + item.name + ' to ' + npc.name.text+ '.')],
                                info = self.__info__(self.GIVE, item, npc), online=True)
    
    def create_receive_event(self, item, npc):        
        return self.event_engine.add_event(preconditions = [self.code_engine.create_always_fail_precon()],
                                actions = [self.code_engine.create_message_action('you receive ' + item.name + ' from ' + npc.name.text + '.')],
                                info = self.__info__(self.RECEIVE, item, npc))
    
    def inventory_list(self):
        inv = []
        for item in Item.objects.all():
            related = eval(self.related(item))
            inve = eval(self.inventory(item))
            if Event.objects.filter(related):
                related = Event.objects.filter(related)
                inve = Event.objects.filter(inve)
                if (related.latest() in inve):
                    inv.append(item)
        return inv
        
    def pick(self, item):
        return 'Q(info__istartswith="' + self.PICK + ':' + str(item.id)+'")'

    def drop(self, item):
        return 'Q(info__istartswith="' + self.DROP + ':' + str(item.id)+'")'
    
    def give(self, item):
        return 'Q(info__istartswith="' + self.GIVE + ':' + str(item.id)+'")'
        
    def receive(self, item):
        return 'Q(info__istartswith="' + self.RECEIVE + ':' + str(item.id)+'")'
        
    def related(self, item):
        return '(' + self.pick(item) + '|' + self.drop(item) + '|' + self.give(item) + '|' + self.receive(item) + ')&Q(timestamp__isnull=False)'        
    
    def inventory(self, item):
        return '(' + self.pick(item) + '|' + self.receive(item) + ')'
    
    def is_in_inventory(self, item, negate=False):
        return self.code_engine.create_latest_event_precon(self.related(item), self.inventory(item), negate)
    
    def __info__(self, info, *args):
        return info + ":" + ":".join([str(arg.id) for arg in args])